/**
 * Copyright © 2013 Creativor Studio.
 * About license information, please see LICENSE.txt.
 */
package org.creativor.rayson.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;

import org.creativor.rayson.api.Protocol;
import org.creativor.rayson.api.exception.IllegalProtocolException;
import org.creativor.rayson.api.server.RpcContainer;
import org.creativor.rayson.api.server.exception.DuplicateServiceException;
import org.creativor.rayson.api.server.exception.NoSuchServiceException;
import org.creativor.rayson.server.transport.nio.NioListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Server of Rayson.
 * 
 * @author creativor
 */
public class RpcServer implements RpcContainer {
	private static Logger LOGGER = LoggerFactory.getLogger(RpcServer.class);

	private ServerSocketChannel socketChannel;
	private int portNumber;
	private String name;

	private NioListener listener;

	/**
	 * Construct a new server by giving a port number.
	 * 
	 * @param portNumber
	 */
	public RpcServer(final int portNumber) {
		this.portNumber = portNumber;
	}

	@Override
	@SafeVarargs
	public final void addService(final Protocol service,
			final Class<? extends Protocol>... protocols)
			throws DuplicateServiceException, IllegalProtocolException {
		// TODO Auto-generated method stub

	}

	/**
	 * Gets the port number.
	 * 
	 * @return the port number
	 */
	public int getPortNumber() {
		return portNumber;
	}

	/**
	 * @return the socketChannel
	 */
	ServerSocketChannel getSocketChannel() {
		return socketChannel;
	}

	@Override
	public void removeService(final Class<? extends Protocol> protocol)
			throws NoSuchServiceException {
		// TODO Auto-generated method stub

	}

	/**
	 * Shut this server down.
	 */
	public void shutdown() {

	}

	/**
	 * Start this server.
	 * 
	 * @throws IOException
	 *             If start the server failed.
	 */
	public void start() throws IOException {
		this.socketChannel = ServerSocketChannel.open();
		this.socketChannel.configureBlocking(false);
		final InetSocketAddress socketAddress = new InetSocketAddress(
				getPortNumber());
		this.socketChannel.socket().bind(socketAddress);
		this.portNumber = socketAddress.getPort();
		this.name = this.getClass().getSimpleName() + " on: " + this.portNumber;
		this.listener = new NioListener(this, socketChannel);
		this.listener.start();
		LOGGER.info("Server " + this.toString() + " started....");
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("portNumber:" + this.portNumber);
		sb.append(", name:" + this.name);
		sb.append("}");
		return sb.toString();
	}

}
